﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using Newtonsoft.Json;
using T.ServiceComponent.Database.Service;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.ServiceComponent.Error;
using T.FAS.Runtime.Base.Entity;
using Newtonsoft.Json.Linq;

namespace T.FAS.Runtime.DataModel.Dao
{
    /// <summary>
    /// SDO Logic层，复用DataObjectLogic，重写InitializeDO方法
    /// </summary>
    public class StaticDataObjectLogic : DataObjectLogic
    {
        private readonly StaticDataObjectPresetDataELBDao _staticDataObjectPresetDataELBDao = new StaticDataObjectPresetDataELBDao();
        /// <summary>
        /// 复写DataObjectManager中默认的MetaDataID
        /// </summary>
        public override string MetaDataID => "StaticDataObject";
        /// <summary>
        /// 复写DataObjectManager中默认的MetaDataName
        /// </summary>
        public override string MetaDataName => "静态数据对象";

        public override void InitializeDO(DataObject @do)
        {
            base.InitializeDO(@do);
        }

        /// <summary>
        /// 保存DataObject
        /// </summary>
        /// <param name="dataObject"></param>
        public override void SaveDataObject(DataObject dataObject)
        {
            base.SaveDataObject(dataObject);
        }

        /// <summary>
        /// 提供更新SDO预置数据的方法，仅供状态机使用
        /// </summary>
        /// <param name="sdoID"></param>
        /// <param name="states"></param>
        public void SyncPresetData(string sdoID, Dictionary<int, string> states)
        {
            if (string.IsNullOrEmpty(sdoID) || states == null || states.Count == 0)
                return;
            List<Dictionary<string, object>> presetData = new List<Dictionary<string, object>>();
            var sdo = GetDataObjectByID(sdoID);
            if (sdo == null) return;

            DataColumn pkCol = sdo.Columns.FirstOrDefault(col => col.IsPkColumn);
            if (pkCol.ApplicationDataType != DataType.Int.ToString())   //如果SDO主键不是int类型，返回
                return;
            DataColumn nameCol = default;
            //固定取Name列
            nameCol = sdo.Columns.FirstOrDefault(col => string.Equals(col.ColumnName, "name", StringComparison.OrdinalIgnoreCase));
            if(nameCol == null || nameCol.ApplicationDataType != DataType.String.ToString())
            {
                nameCol = sdo.Columns.FirstOrDefault(col => col.ColumnOrder == pkCol.ColumnOrder + 1);
                if(nameCol == null || nameCol.ApplicationDataType != DataType.String.ToString())
                {
                    nameCol = sdo.Columns.FirstOrDefault(col => col.ApplicationDataType == DataType.String.ToString());
                }
            }
            if (nameCol == null)
                return;

            var presetDataObj = _staticDataObjectPresetDataELBDao.GetStaticDataObjectPresetDatas(sdoID);
            var contentJson = presetDataObj.Content;
            //尝试更新预置数据Json，更新失败则覆写
            if (!string.IsNullOrEmpty(contentJson))
            {
                try
                {
                    bool validateFlag = true;
                    var jarr = JArray.Parse(contentJson);
                    List<JToken> needDropTokens = new List<JToken>();
                    List<int> ids = new List<int>();
                    foreach (var token in jarr)
                    {
                        var obj = token as JObject;
                        JProperty pkProp = obj.Property(pkCol.ColumnName);
                        JProperty nameProp = obj.Property(nameCol.ColumnName);
                        if (pkProp == null)
                        {
                            validateFlag = false;
                            break;
                        }
                        int pkVal = int.Parse((pkProp.Value as JValue).Value.ToString());
                        string nameVal = (nameProp.Value as JValue).Value.ToString();
                        if (states.ContainsKey(pkVal))
                        {
                            if (!string.Equals(nameVal, states[pkVal]))
                            {
                                //同步最新列名
                                (nameProp.Value as JValue).Value = states[pkVal];
                            }
                            ids.Add(pkVal);
                        }
                        else
                        {
                            needDropTokens.Add(token);
                        }
                    }
                    if (validateFlag)
                    {
                        //删除不存在的记录
                        if (needDropTokens.Count > 0)
                            needDropTokens.ForEach(token => jarr.Remove(token));

                        var needAddRecords = states.Keys.Except(ids);
                        foreach (var addId in needAddRecords)
                        {
                            JObject obj = new JObject
                            {
                                [pkCol.ColumnName] = new JValue(addId),
                                [nameCol.ColumnName] = new JValue(states[addId])
                            };
                            jarr.Add(obj);
                        }
                        presetDataObj.Content = jarr.ToString();
                        _staticDataObjectPresetDataELBDao.DeleteStaticDataObjectPresetData(sdoID);
                        _staticDataObjectPresetDataELBDao.CreateStaticDataObjectPresetData(presetDataObj);
                        return;
                    }
                }
                catch
                {
                }
            }
            

            foreach (var state in states.Keys)
            {
                var dict = new Dictionary<string, object>();
                dict[pkCol.ColumnName] = state;
                dict[nameCol.ColumnName] = states[state];
                presetData.Add(dict);
            }
            var newData = JsonConvert.SerializeObject(presetData);
            LocalLogService.Write(new { Msg = "修改预置数据", Data = presetData });

            var presetDataEntity = ConstructPresetDataEntity(sdo);
            presetDataEntity.Content = newData;
            //清除预置数据
            _staticDataObjectPresetDataELBDao.DeleteStaticDataObjectPresetData(sdoID);
            _staticDataObjectPresetDataELBDao.CreateStaticDataObjectPresetData(presetDataEntity);
        }

        /// <summary>
        /// 提供更新SDO预置数据的方法，仅供状态机使用
        /// </summary>
        /// <param name="sdoID"></param>
        /// <param name="States"></param>
        public void SavePresetData(string sdoID, string content)
        {
            if (string.IsNullOrEmpty(sdoID) || string.IsNullOrEmpty(content))
                return;
            var sdo = GetDataObjectByID(sdoID);
            if (sdo == null) return;
             
            var presetDataEntity = ConstructPresetDataEntity(sdo);
            presetDataEntity.Content = content;
            //清除预置数据
            _staticDataObjectPresetDataELBDao.DeleteStaticDataObjectPresetData(sdoID);
            _staticDataObjectPresetDataELBDao.CreateStaticDataObjectPresetData(presetDataEntity);
        }

        /// <summary>
        /// 构造SDO预置数据实体
        /// </summary>
        /// <param name="dataObject"></param>
        /// <returns></returns>
        private StaticDataObjectPresetData ConstructPresetDataEntity(DataObject dataObject)
        {
            StaticDataObjectPresetData staticDataObjectPresetData = new StaticDataObjectPresetData
            {
                ID = Guid.NewGuid().ToString(),
                DataObjectID = dataObject.ID,
                Creator = UserUtil.GetCurrentUserName(),
                CreateTime = DateTime.Now,
            };
            staticDataObjectPresetData.LastModifier = staticDataObjectPresetData.Creator;
            staticDataObjectPresetData.LastModifyTime = staticDataObjectPresetData.CreateTime;
            return staticDataObjectPresetData;
        }
     
    }
}
